package com.changli02.reference;

import com.changli02.reference.data.Employee;
import org.junit.Test;

import java.util.Comparator;
import java.util.function.BiPredicate;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Supplier;

public class MethodTest {
    @Test
    public void test() {

        /*
        *
        * 情况1:对象 ::实例方法
            要求:函数式接口中的抽象方法a与其内部实现时调用的对象的某个方法b的形参列表和返回值类型都相同(或一致)。
            此时，可以考虑使用方法b实现对方法a的替换、覆盖。此替换或覆盖即为方法引用。
            往意:此方法b是非静态的方法，需要对象调用。
        *
        *
        *
        *
        * */
        Consumer<String> con1 = new Consumer<String>(){
            @Override
            public void accept(String s) {
                System.out.println(s);
            }
        };

        Consumer<String> con2 = s->System.out.println(s);

        Consumer<String> con3 = System.out::println;

        String s = "I love U";
        con1.accept(s);
        con2.accept(s);
        con3.accept(s);

    }
    @Test
    public void test2() {
        Employee emp = new Employee("Sail",20);

        Supplier<String> sup = new Supplier<String>() {
            @Override
            public String get() {
                return emp.getName();
            }
        };
        Supplier<String> sup2 = () -> emp.getName();
        Supplier<String> sup3 = emp::getName;

        System.out.println(sup.get());
        System.out.println(sup2.get());
        System.out.println(sup3.get());


    }

    /*
    * 情况2:类::静态方法
    要求:函数式接口中的抽象方法a与其内部实现时调用的类的某个静态方法b的形参列表和返回值类型都相同(或一致)。
    此时，可以考虑使用方法b实现对方法a的替换、覆盖。此替换或覆盖即为方法引用。
    注意:此方法b是静态的方法，需要类调用。
    *
    *
    *
    *
    *
    * */



    @Test

    public void test3() {
        //1.
        Function<Double,Long> f = new Function<Double, Long>() {
            @Override
            public Long apply(Double aDouble) {
                return Math.round(aDouble);
            }
        };
        //2.
        Function<Double,Long> f1 = (Double aDouble)-> Math.round(aDouble);

        //3.
        Function<Double,Long> f3 = Math::round;




    }

    /*
    *   情况3:类::实例方法
        要求:函数式接口中的抽象方法a与其内部实现时调用的对象的某个方法b的返回值类型相同。
    *   同时，抽象方法a中有n个参数，方法b中有n-1个参数，且抽象方法a的第1个参数作为方法b的调用者，
    *   且抽象方法a的后n-1个参数与方法b的n-1个参数的类型相同(或一致)。
    *   则可以考虑使用方法b实现对方法a的替换、覆盖。此替换或覆盖即为方法引用
        注意:此方法b是非静态的方法，需要对象调用。
    *
    *
    *
    *
    * */

    @Test
    public void test4() {
        Comparator<String> c1 = new Comparator<String>() {
            @Override
            public int compare(String o1, String o2) {
                return o1.compareTo(o2);
            }
        };

        Comparator<String> c2 = (o1,o2) ->o1.compareTo(o2);
        Comparator<String> c3 = String::compareTo;



    }

    @Test


    public void test5() {
        BiPredicate<String,String> b = new BiPredicate<String,String>() {
            @Override
            public boolean test(String s, String s2) {
                return s.equals(s2);
            }
        };

        BiPredicate<String,String> b1 = (a,b2)->a.equals(b2);

        BiPredicate<String,String> b2 = String::equals;



    }
    @Test
    public void test6() {


        Function<Employee,String> f = new Function<Employee, String>() {

            @Override
            public String apply(Employee employee) {
                return employee.getName();
            }
        };

        Function<Employee,String> f1 = emp->emp.getName();
        Function<Employee,String> f2 = Employee::getName;
    }


}
